/*
 * Station.java
 * 
 * Copyright 2008 David D. Emory
 * 
 * This file is part of Five Points. See <http://www.fpdev.org> for
 * additional information regarding the project.
 * 
 * Five Points is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * Five Points is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with Five Points.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.fpdev.core.transit;

import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import org.fpdev.core.basenet.BLink;
import org.fpdev.core.basenet.BNode;
import org.fpdev.apps.rtemaster.gui.map.MapCanvas;
import org.fpdev.apps.rtemaster.gui.map.MapDrawable;
import org.fpdev.core.basenet.BaseNetwork;

public class Station implements MapDrawable {

  private List<StationNode> nodes_;
  private List<StationLink> links_;
  private String id_,  name_;
  private boolean initialized_;

  public Station(String id, String name) {
    id_ = id;
    name_ = name;
    initialized_ = true;
    nodes_ = new LinkedList<StationNode>();
    links_ = new LinkedList<StationLink>();
  }

  public String getID() {
    return id_;
  }

  public String getName() {
    return name_;
  }

  public Point2D getCoordinate() {
    double x = 0, y =0, count = nodes_.size();
    for(StationNode node : nodes_) {
      x += node.getNode().getX();
      y += node.getNode().getY();
    }
    return new Point2D.Double(x/count, y/count);
  }

  public boolean initialized() {
    return initialized_;
  }
  
  public void initNetworkElements(BaseNetwork baseNet) {
    for(StationNode node : nodes_) node.initNode(baseNet);
    for(StationLink link : links_) link.initLink(baseNet);

  }

  public Collection<BNode> getNodes() {
    List<BNode> toRet = new LinkedList<BNode>();
    for(StationNode node : nodes_) toRet.add(node.getNode());
    return toRet;
  }

  public Collection<Integer> getNodeIDs() {
    List<Integer> toRet = new LinkedList<Integer>();
    for(StationNode node : nodes_) if(node.getNodeID() > 0) toRet.add(node.getNodeID());
    return toRet;
  }

  public void addNode(BNode node) {
    addNode(node, "");
  }

  public void addNode(BNode node, String name) {
    if (includesNode(node)) return;
    node.setStation(this);
    nodes_.add(new StationNode(node, name));
  }

  public void addNode(int nodeID, String name) {
    initialized_ = false;
    nodes_.add(new StationNode(nodeID, name));
  }

  public void removeNode(BNode node) {
    for(StationNode snode : nodes_)
      if(snode.getNode() == node) {
        nodes_.remove(snode);
        node.removeStation();
        return;
      }
  }

  public boolean includesNode(BNode node) {
    for(StationNode snode : nodes_)
      if(snode.getNode() == node) return true;
    return false;
  }

  public String getNodeName(BNode node) {
    for(StationNode snode : nodes_)
      if(snode.getNode() == node) return snode.getName();
    return "";
  }

  public boolean setNodeName(BNode node, String name) {
    for(StationNode snode : nodes_)
      if(snode.getNode() == node) {
        snode.setName(name);
        return true;
      }
    return false;
  }

  public int getNodeCount() {
    return nodes_.size();
  }

  public Collection<BLink> getLinks() {
    List<BLink> toRet = new LinkedList<BLink>();
    for(StationLink slink : links_) toRet.add(slink.getLink());
    return toRet;
    //return links_;
  }

  public Collection<Integer> getLinkIDs() {
    List<Integer> toRet = new LinkedList<Integer>();
    for(StationLink slink : links_) if(slink.getLinkID() > 0) toRet.add(slink.getLinkID());
    return toRet;
  }

  public void addLink(BLink link) {
    if (includesLink(link)) return;
    link.setStation(this);
    links_.add(new StationLink(link));
  }

  public void addLink(int linkID) {
    initialized_ = false;
    links_.add(new StationLink(linkID));
  }

  public void removeLink(BLink link) {

    for(StationLink slink : links_)
      if(slink.getLink() == link) {
        links_.remove(slink);
        link.removeStation();
        return;
      }
  }

  public boolean includesLink(BLink link) {
    for(StationLink slink : links_)
      if(slink.getLink() == link) return true;
    return false;
  }

  public int getLinkCount() {
    return links_.size();
  }

  public Rectangle2D.Double getBoundingBox() {
    Rectangle2D.Double rect = null;
    for(BNode node : getNodes()) {
      if (rect == null) {
        rect = new Rectangle2D.Double(node.getX(), node.getY(), 0, 0);
      } else {
        rect.add(node.getX(), node.getY());
      }
    }

    for(BLink link : getLinks()) {
      if (rect == null) {
        rect = new Rectangle2D.Double(link.getX1(), link.getY1(), 0, 0);
      } else {
        rect.add(link.getX1(), link.getY1());
      }
      rect.add(link.getX2(), link.getY2());
    }
    return rect;
  }

  public void draw(MapCanvas canvas) {
    
    for(BNode node : getNodes()) node.drawSel(canvas);
    for(BLink link : getLinks()) link.drawSel(canvas);

    for(BNode node : getNodes()) node.draw(canvas);
    //for(BLink link : getLinks()) link.draw(canvas);

  }

  public Collection<SubRoute> getServices(BaseNetwork net) {
    Set<SubRoute> results = new HashSet<SubRoute>();
    for(StationNode node : nodes_) {
      for(BLink link : net.incidentLinks(node.getNode())) {
        Iterator<SubRoute> subIter = (link.getFNode() == node.getNode()) ? link.getSubRoutesFT() : link.getSubRoutesTF();
        while(subIter.hasNext()) results.add(subIter.next());
      }
    }
    return results;
  }

  // StationNodeInfo class

  public class StationNode {

    private int nodeID_;
    private BNode node_;
    private String name_;

    public StationNode(int nodeID, String name) {
      nodeID_ = nodeID;
      name_ = name;
    }

    public StationNode(BNode node, String name) {
      nodeID_ = 0;
      node_ = node;
      name_ = name;
    }

    public void initNode(BaseNetwork baseNet) {
      if(node_ != null) return;
      node_ = baseNet.getNodeFromID(nodeID_);
      node_.setStation(Station.this);
    }

    public int getNodeID() {
      return nodeID_;
    }

    public BNode getNode() {
      return node_;
    }

    public String getName() {
      return name_;
    }

    public void setName(String name) {
      name_ = name;
    }
  }


  // StationLinkInfo class

  public class StationLink {

    private int linkID_;
    private BLink link_;

    public StationLink(int linkID) {
      linkID_ = linkID;
    }

    public StationLink(BLink link) {
      link_ = link;
    }

    public void initLink(BaseNetwork baseNet) {
      if(link_ != null) return;
      link_ = baseNet.getLinkFromID(linkID_);
      link_.setStation(Station.this);
    }

    public BLink getLink() {
      return link_;
    }

    public int getLinkID() {
      return linkID_;
    }

  }

}
























